// =============================================================
// CInfoMap
// ---------------------------------------
// Author : Woo-Hyun Kim
// Email : woorung@icu.ac.kr or woorung@nhncorp.com
// Date : Jul. 10, 2006
//----------------------------------------------------------------------
#include "CInfoMap.h"
//----------------------------------------------------------------------
//CInfoMap::CInfoMap(char *imap_file) : CCubeScript()
CInfoMap::CInfoMap(char *imap_file) : CScript()
{
    if(imap_file==NULL) {
        cerr << "not found file and not opened : " << imap_file << endl;
        exit(-1);
    }

	current_pos = 0;

	imap_file_name = imap_file;

	imap = get_imap(imap_file);

	addDefaultParameters();
	replaceActionAVs();
	replaceTaskAVs();
	replaceCommonAVs();
	makeupTasks();
}
//----------------------------------------------------------------------
//CInfoMap::CInfoMap(char *imap_file, vector<string> &args) : CCubeScript()
CInfoMap::CInfoMap(char *imap_file, vector<string> &args) : CScript()
{
	if(imap_file==NULL) {
		cerr << "not found file and not opened : " << imap_file << endl;
		exit(-1);
	}

	current_pos = 0;

	imap_file_name = imap_file;

	char tmp[50];
	string args_all = "";

	// add parameters of command line
	for(int i=0;i<args.size();i++) {
		sprintf(tmp, "@[%d]", i+1);
		string attr = tmp;

		default_params[attr] = args[i];

		args_all += args[i] + " ";
	}

	sprintf(tmp, "@%d", 0);
	string attr = tmp;
	default_params[attr] = args_all;

	imap = get_imap(imap_file);

	addDefaultParameters();
	replaceActionAVs();
	replaceTaskAVs();
	replaceCommonAVs();
	makeupTasks();
}
//----------------------------------------------------------------------
CInfoMap::~CInfoMap()
{
}
//----------------------------------------------------------------------
Tinfo_map *CInfoMap::getIMap()
{
	return imap;
}
//----------------------------------------------------------------------
int CInfoMap::addDefaultParameters()
{
	map<string,string>::iterator param = default_params.begin();
	while(param!=default_params.end()) {
		int found = 0;
		for(int i=0;i<imap->common_task.attr_val.size();i++) {
			string attr = imap->common_task.attr_val[i].attr;
			string val = imap->common_task.attr_val[i].val;

			if(param->first==attr) {
				found = 1;
				break;
			}
		}

		if(found==0) {
			Tattr_val attr_val;
			attr_val.attr = param->first;

			if(param->first=="@sp_tdl_file_name") attr_val.val = default_params["@sp_planet_working_path"] + "/" + imap_file_name;
			else attr_val.val = param->second;

			imap->common_task.attr_val.push_back(attr_val);
		}

		param++;
	}
}
//----------------------------------------------------------------------
int CInfoMap::replaceCommonAVs()
{
	for(int i=0;i<imap->common_task.attr_val.size();i++) {
		string attr = imap->common_task.attr_val[i].attr;
		string val = imap->common_task.attr_val[i].val;

		// replace some variables in the common attribute-value part
		for(int j=0;j<imap->common_task.attr_val.size();j++) { 
			replaceVariable(imap->common_task.attr_val[j].val, attr, val);
		}
		
		for(int j=0;j<imap->tasks.size();j++) { // tasks
			// replace some variables in each task part
			for(int k=0;k<imap->tasks[j].attr_val.size();k++) { // each task
				replaceVariable(imap->tasks[j].attr_val[k].val, attr, val);
			}

			// replace some variables in the specified actions of each task
			for(int k=0;k<imap->tasks[j].actions.size();k++) {  // actons
				// replace the commands in the specific action
				for(int l=0;l<imap->tasks[j].actions[k].commands.size();l++) {
					replaceVariable(imap->tasks[j].actions[k].commands[l], attr, val);
				}
			}

			// replace some variables in the specified invokers of each task
			for(int k=0;k<imap->tasks[j].invokers.size();k++) {
				map<string,string>::iterator param = imap->tasks[j].invokers[k].params.begin();
				while(param!=imap->tasks[j].invokers[k].params.end()) {
					replaceVariable(param->second, attr, val);
					param++;
				}
			}
		}
	}

	return 0;
}
//----------------------------------------------------------------------
int CInfoMap::replaceTaskAVs()
{
	for(int i=0;i<imap->tasks.size();i++) { // tasks
		for(int j=0;j<imap->tasks[i].attr_val.size();j++) {
			string attr = imap->tasks[i].attr_val[j].attr;
			string val = imap->tasks[i].attr_val[j].val;

			// replace the variables in the specific task
			for(int k=0;k<imap->tasks[i].attr_val.size();k++) {
				replaceVariable(imap->tasks[i].attr_val[k].val, attr, val);
			}

			// replace the variables of the actions in the specific task
			for(int k=0;k<imap->tasks[i].actions.size();k++) {
				// replace the commands in the specific action
				for(int l=0;l<imap->tasks[i].actions[k].commands.size();l++) {
					replaceVariable(imap->tasks[i].actions[k].commands[l], attr, val);
				}
			}

			// replace some variables in the specified invokers of each task
			for(int k=0;k<imap->tasks[i].invokers.size();k++) {
				map<string,string>::iterator param = imap->tasks[i].invokers[k].params.begin();
            	while(param!=imap->tasks[i].invokers[k].params.end()) {
					replaceVariable(param->second, attr, val);
					param++;
				}
			}
		}
	}

	return 0;
}
//----------------------------------------------------------------------
int CInfoMap::replaceActionAVs()
{
	for(int i=0;i<imap->tasks.size();i++) {
		// invokers ---------
		for(int j=0;j<imap->tasks[i].invokers.size();j++) {
			map<string,string>::iterator param = imap->tasks[i].invokers[j].params.begin();
			while(param!=imap->tasks[i].invokers[j].params.end()) {
				string attr = param->first;
				string val = param->second;

				// replace the values of params in the specific invoker
				map<string,string>::iterator target = imap->tasks[i].invokers[j].params.begin();
				while(target!=imap->tasks[i].invokers[j].params.end()) {
					replaceVariable(target->second, attr, val);
					target++;
				}

				param++;
			}
		}
	}
}
//----------------------------------------------------------------------
int CInfoMap::makeupTasks()
{
	// extract common task variables
	// (these will be shared in all of the tasks)
	map<string,string> common_task_variables;
	for(int i=0;i<imap->common_task.attr_val.size();i++) {
		string attr = imap->common_task.attr_val[i].attr;
		string val = imap->common_task.attr_val[i].val;

		char mark = attr[0];
		if(mark=='@') common_task_variables[attr] = val;
	}

	for(int i=0;i<imap->tasks.size();i++) {
		// generate a new task
		CTask task(imap->tasks[i].name);

		// extract task variables
		// (these will be used just in each task)
		map<string,string> task_variables;
		for(int j=0;j<imap->tasks[i].attr_val.size();j++) {
			string attr = imap->tasks[i].attr_val[j].attr;
			string val = imap->tasks[i].attr_val[j].val;

			char mark = attr[0];
			if(mark=='@') task_variables[attr] = val;
		}

		// register the common task variables
		task.registerCommonTaskVariables(common_task_variables);
		// register the task variables
		task.registerTaskVariables(task_variables);

		// register each action in the given task in order
		int last_apos = 0;
		int last_ipos = 0;
		for(int j=0;j<imap->tasks[i].ordered_action_list.size();j++) {
			string aname = imap->tasks[i].ordered_action_list[j];
			char mark = aname[0];

			// in case of external actions
			if(mark!='@') {
				for(int k=last_apos;k<imap->tasks[i].actions.size();k++) {
					if(aname==imap->tasks[i].actions[k].name) {
						// save the next position of the matching action
						last_apos = k+1;

						// generate a new action in the given task
						CAction action(imap->tasks[i].actions[k].type, aname);

						// register the commands in the action
						for(int l=0;l<imap->tasks[i].actions[k].commands.size();l++) {
							action.registerCommand(imap->tasks[i].actions[k].commands[l]);
						}

						// register the new action
						task.registerAction(action);

						break;
					}
				}
			}
			// in case of internal actions(invokers)
			else if(mark=='@') {
				for(int k=last_ipos;k<imap->tasks[i].invokers.size();k++) {
					if(aname==imap->tasks[i].invokers[k].name) {
						// save the next position of the matching action
							last_ipos = k+1;

						// generate a new action in the given task
						CAction action(imap->tasks[i].invokers[k].type, aname);

						// register the common task variables
						action.registerCommonTaskVariables(common_task_variables);
						// register the task variables
						action.registerTaskVariables(task_variables);
						// register the parameters in the action
						action.registerActionVariables(imap->tasks[i].invokers[k].params);

						// register the new internal action(invoker)
						task.registerAction(action);

						break;
					}
				}
			}
		}

		// register the new task in the task list
		tasks.push_back(task);
	}

	current_pos = tasks.size();
	return current_pos;
}
//----------------------------------------------------------------------
int CInfoMap::hasMoreTasks()
{
	return current_pos;
}
//----------------------------------------------------------------------
CTask &CInfoMap::getNextTask()
{
	int i = tasks.size() - current_pos--;
	return tasks[i];
}
//----------------------------------------------------------------------
